//
// GPSMapEdit
// (c) Konstantin Galichsky (kg@infratel.com), 2002-2004
//
// Common protocol scenario.
//

# include "StdAfx.h"
# include "GpsProtocol.h"
# include "ComPort.h"
# include "Positioning.h"

bool CGpsProtocol::Run (CComPort * _pPort, size_t _cPort, HANDLE _hStopEvent, HANDLE _hReadyEvent) {
	// Report protocol name.
	string_t strProtocolName;
	this->GetName (strProtocolName);
	char strStatus [256];
	::sprintf (strStatus, "Trying %s...", strProtocolName.c_str ());
	SetPositioningStatus (strStatus);

	// Clean the input buffer.
	::PurgeComm (* _pPort, PURGE_TXCLEAR | PURGE_RXCLEAR);

	// Start the protocol.
	this->Init (_pPort);
	CGpsProtocol::CStarter ps (this);

	bool bTry = true;

	while (true) {
		// Wait for data.
		DWORD dwDataSize = 0;
		while (true) {
			if (bTry) {
				const HANDLE events [2] = {_hStopEvent, _hReadyEvent};
				if (::WaitForMultipleObjects (2, events, FALSE, 20) != WAIT_TIMEOUT)
					return true;
			} else {
				if (::WaitForSingleObject (_hStopEvent, 20) == WAIT_OBJECT_0)
					return true;
			}

			dwDataSize = _pPort->GetInQueueSize ();
			if (dwDataSize > 0)
				break;

			const CGpsProtocol::Status_t s = this->OnDataReceived (NULL, 0);
    		if (s == CGpsProtocol::stSureError) {
				if (! bTry) {
					::ResetEvent (_hReadyEvent);
					SetPositioningStatus ("No data detected.");
					::WaitForSingleObject (_hStopEvent, 2000);
				}
				return false;
			}
		}

		// Read the data.
		BYTE pData [1024];
		DWORD dwRead = 0;
		::ReadFile (* _pPort, pData, dwDataSize < sizeof (pData) ? dwDataSize : sizeof (pData), & dwRead, NULL);

		// Analyze the data.
		const CGpsProtocol::Status_t s = this->OnDataReceived (pData, dwRead);
		if (s == stSureError) {
			if (! bTry) {
				::ResetEvent (_hReadyEvent);
				SetPositioningStatus ("Protocol failure.");
				::WaitForSingleObject (_hStopEvent, 2000);
			}
			return false;
		}

		if (bTry && s == stSureOK) {
			bTry = false;

			::SetEvent (_hReadyEvent);

			::sprintf (strStatus, "%s over COM%d", strProtocolName.c_str (), _cPort);
			SetPositioningStatus (strStatus);
		}
	}
}